<?php

namespace app\models\tableModel;

use app\models\cacheModel\AdminRoleModel as AdminRoleCacheModel;
use app\models\CommonModel;
use app\models\table\AdminUser;
use app\models\tableModel\AdminRoleModel as AdminRoleTableModel;
use yii\db\Exception;
use yii\helpers\ArrayHelper;

/**
 * 操作员管理[Model]
 * User: Administrator
 * Date: 2020/09/19
 * Time: 10:11:31
 * @property string $password
 */
class AdminUserModel extends AdminUser
{

    /**
     * 状态 列表
     * @var array
     */
    private static $statusList = [
        'disabled' => -1,
        'normal' => 0,
        'open' => 1
    ];
    /**
     * 状态文本 列表
     * @var array
     */
    private static $statusListText = [
        -1 => '已禁用',
        0 => '未审核',
        1 => '已开启'
    ];
    /**
     * 排序最大值
     * @var int
     */
    protected static $sortMax = 9999999;
    /**
     * 排序最小值
     * @var int
     */
    protected static $sortMin = -999999;

    /**
     * 条件
     * @var array
     */
    public $where = [];

    /**
     * 静态错误暂存
     * @var
     */
    public static $error_;

    /**
     * 暂存角色列表
     * @var AdminRoleCacheModel
     */
    protected $roleList;

    /**
     * 新密码
     * @var string
     */
    public $password;
    /**
     * 使用新密码字段
     */
    const addUser = 'add_user';

    /**
     * 规则验证
     * @return array
     */
    public function rules()
    {

        $parent = parent::rules();
        // 状态
        $statusList = array_values(self::getStatList());

        return ArrayHelper::merge($parent, [
            [['status'], 'in', 'range' => $statusList, 'message' => '状态不合法'],
            [['role_id'], 'checkRoleId'],
            [['password'], 'required', 'on' => self::addUser],
        ]);
    }

    /**
     * 重写label的 文字
     */
    public function attributeLabels()
    {

        $parent = parent::attributeLabels();
        return array_merge($parent, [
            'id' => '编号',
            'add_time' => '添加时间',
            'update_time' => '更新时间',
            'status' => '状态',
            'password' => '密码'
        ]);
    }

    /**
     * 场景
     * @return array
     */
    public function scenarios()
    {

        $scenarios = parent::scenarios();
        return ArrayHelper::merge($scenarios, [
            // 使用密码的场景
            self::addUser => [
                'password'
            ]
        ]);
    }

    /**
     * 检测角色是否合法
     * @param null $attributeNames
     * @param bool $clearErrors
     * @return bool
     */
    public function checkRoleId($attributeNames = null, $clearErrors = true)
    {

        $roleInfo = AdminRoleModel::loadModel($this->$attributeNames);
        if (!$roleInfo) {
            $this->addError('role_id', '找不到角色信息');
            return false;
        }

        if ($roleInfo['status'] != AdminRoleModel::getStatOpen()) {
            $this->addError('role_id', '该角色已禁用');
            return false;
        }

        return true;
    }

    /**
     * 加载整体[Model]
     * @param null $id 编号
     * @param string $scenario 场景
     * @return AdminUserModel|\yii\db\ActiveQuery|null
     */
    public static function loadModel($id = null, $scenario = 'default')
    {

        // 实力化类
        $model = new self();

        // [id]是[true]返回
        if ($id === true) {
            return $model::find();
        } else if (!empty($id)) { // 有[id]去查询
            $model = $model::findOne($id);
        }

        // 条目不存在或者需要[find]都返回 - 无法加载场景
        if (!$model || $id === true) {
            return $model;
        }

        // 场景
        $sceList = array_keys($model->scenarios());
        if (!empty($scenario) && in_array($scenario, $sceList)) $model->setScenario($scenario);

        return $model;
    }

    /**
     * 获取全部列表
     * @param $page
     * @param $limit
     * @param null $filed
     * @return array|\yii\db\ActiveRecord[]
     */
    public function getList($page, $limit, $filed = null)
    {

        // 条件
        $where = $this->where;

        // 当前页面计算
        $page = (($page - 1) < 0 ? 0 : ($page - 1));

        // 查找的 字段空的 就默认给列表
        if (!$filed) $filed = '*';

        // 基础 where加载完毕
        $base = $this::find()->select($filed)->where($where);

        // 数据的获取 分页等
        $list = $base->offset($page * $limit)
            ->limit($limit)
            ->asArray()->all();

        $roleIdList = array_column($list, 'role_id');
        // 角色列表
        $this->roleList = AdminRoleTableModel::loadModel()
            ->loadWhere([
                'AND',
                ['=', 'status', AdminRoleTableModel::getStatOpen()]
            ])->getList(1, 200);
        $this->roleList = array_column($this->roleList, null, 'id');

        // 格式化数据
        foreach ($list as $k => &$v) {

            // 更新时间
            if (!empty($v['update_time'])) {
                $v['update_time_text'] = date('Y-m-d H:i:s', $v['update_time']);
                $v['update_time_text_s'] = date('Y-m-d', $v['update_time']);
            }

            // 状态文本
            if (isset($v['status'])) {
                $v['status_text'] = self::getStatusText($v['status']);
            }

            // 角色编号
            if (isset($v['role_id']) && !empty($this->roleList[$v['role_id']]['name'])) {
                $v['role_name'] = $this->roleList[$v['role_id']]['name'];
            } else {
                $v['role_name'] = '--';
            }
        }

        return $list;
    }

    /**
     * 加载条件
     * @param $where
     * @return $this
     */
    public function loadWhere($where)
    {

        // 条件不存在
        if (empty($where)) {

            return $this;
        }

        // 如果[where][0]是'and' 直接赋值
        $canRetList = ['and', 'or', 'AND', 'OR'];
        if (!empty($where[0]) && in_array($where[0], $canRetList)) {

            $this->where = $where;
            return $this;
        }

        // 不是数组 字符直接 判断
        if (!is_array($where)) {

            // 条件是 有效
            if (!empty($where) && $this->hasAttribute($where))

                $this->where = $where;

            // 条件 无有效
            return $this;
        }

        // 循环  条件是否有效
        $stagingWhere = ['and'];
        foreach ($where as $k => $v) {

            // 首先值是有的，不能是空
            if ($v && is_array($v) && count($v) > 0 && $this->hasAttribute($k)) {

                $stagingWhere[] = ['IN', $k, array_values($v)];
                continue;
            }

            // 首先值是有的，不能是空
            if ($v && $this->hasAttribute($k))

                $stagingWhere[] = ['=', $k, $v];
        }

        // 条件最终赋值
        $this->where = $stagingWhere;

        return $this;
    }

    /**
     * 获取记录总数量
     * @return int|string
     */
    public function getCount()
    {

        // 条件
        $where = $this->where;

        // 基础 where加载完毕
        $count = $this::find()->where($where)->count();

        return $count;
    }

    /**
     * 添加|保存
     * @return bool
     */
    public function saveData()
    {

        $nowTime = time();
        // 添加的话要赋值一些初始数据
        if (empty($this->id)) {

            // 可以是走[mongoId]
            $this->id = CommonModel::newMongoId();
            // 添加时间
            $this->add_time = $nowTime;
            $this->status = self::getStatNormal(); // 状态
            $this->salt = CommonModel::newMongoId(); // 加密字符串
            $this->avatar = empty($this->avatar) ? '/images/thumb/user03.png' : $this->avatar; // 默认头像
            $this->password_hash = self::getPassCrypt($this->password, $this->salt); // 密码
        }

        // 更新时间
        $this->update_time = $nowTime;
        if ($this->hasErrors() || !$this->validate() || !$this->save()) {

            return false;
        }

        // 密码生成
        return true;
    }

    /**
     * 生成新密码
     * @param $passStr
     * @param $salt
     * @return string
     */
    public static function getPassCrypt($passStr, $salt)
    {
        return md5($passStr . $salt);
    }


    /**
     * [静态方法]批量快速更新某些字段|PS：无验证，请在调用此方法前做好各字段验证
     * @param $condition
     * @param array $fieldVal
     * @return bool
     */
    public static function updateField($condition, $fieldVal = [])
    {

        $model = new self();
        foreach ($fieldVal as $k => $v) {

            if (!$model->hasAttribute($k)) {

                unset($fieldVal[$k]);
                continue;
            }
        }

        $db = \Yii::$app->db->createCommand();

        try {

            $db->update(self::tableName(), $fieldVal, $condition)->execute();

            // 否则成功
            return true;
        } catch (Exception $error) {

            // 记录下错误日志
            \Yii::error([

                "`````````````````````````````````````````````````````````",
                "``                      数据库错误                       ``",
                "`` 错误详情: [操作员管理]批量修改[指定字段]失败，   ``",
                "``         {$error->getMessage()}                       ``",
                "`` SQL语句: {$db->getRawSql()}                         ``",
                "`` 错误信息和参数详情:                                     ``",
                "`````````````````````````````````````````````````````````",
                $error->getTraceAsString()
            ], 'normal');

            self::$error_ = empty($error->errorInfo) ?
                $error->getMessage() :
                implode(' | ', $error->errorInfo);

            return false;
        }
    }

    /**
     * 批量添加数据|ps.请事先做好字段数据校验
     * @param array $createData
     * @return bool
     */
    public static function createData($createData = [])
    {

        $db = \Yii::$app->db->createCommand();
        try {

            // 还行写入多条
            $addResult = $db->batchInsert(self::tableName(),
                [
                    'id',
                    'name',
                    'parent_id',
                    'content',
                    'add_time',
                    'module',
                    'controller',
                    'action',
                    'route',
                    'status',
                    'url'
                ], $createData
            )->execute();

            return true;
        } catch (Exception $error) {

            // 记录下错误日志
            \Yii::error([

                "`````````````````````````````````````````````````````````",
                "``                      数据库错误                       ``",
                "`` 错误详情: [操作员管理]批量添加[数据]失败，      ``",
                "``         {$error->getMessage()}                       ``",
                "`` SQL语句: {$db->getRawSql()}                         ``",
                "`` 错误信息和参数详情:                                     ``",
                "`````````````````````````````````````````````````````````",
                $error->getTraceAsString()
            ], 'normal');

            return false;
        }
    }


    /**
     * 获取[正常]状态 值
     * @return mixed|string
     */
    public static function getStatNormal()
    {

        // 最终正常返回
        return self::$statusList['normal'];
    }

    /**
     * 获取[正常]状态 值
     * @return mixed|string
     */
    public static function getStatOpen()
    {

        // 最终正常返回
        return self::$statusList['open'];
    }

    /**
     * 获取[禁用]状态 值
     * @return mixed|string
     */
    public static function getStatDisabled()
    {

        // 最终正常返回
        return self::$statusList['disabled'];
    }

    /**
     * 获取[状态]列表 值
     * @return mixed|string
     */
    public static function getStatList()
    {

        // 最终正常返回
        return self::$statusList;
    }

    /**
     * 获取[状态]文本
     * @param $value
     * @return mixed|string
     */
    public static function getStatusText($value)
    {

        // 列表
        $list = self::$statusListText;
        // 不合法 - 不存在
        if (empty($list[$value]))

            return '--';

        // 最终正常返回
        return $list[$value];
    }

    /**
     * 获取静态错误
     * @return mixed
     */
    public static function getStaticErrors()
    {
        return self::$error_;
    }

    /**
     * 获取成员变量[$roleList]
     * @return AdminRoleCacheModel
     */
    public function getRoleList()
    {
        return $this->roleList;
    }
}
